package com.javaee.weixin.xiaochengxu;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.SqlSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.javaee.weixin.xiaochengxu.dto.PaymentDto;
import com.javaee.weixin.xiaochengxu.dto.UnifiedorderDto;
import com.javaee.weixin.xiaochengxu.dto.UnifiedorderResultDto;
import com.javaee.weixin.xiaochengxu.exception.CommonException;
import com.javaee.weixin.xiaochengxu.tools.IPUtil;
import com.javaee.weixin.xiaochengxu.tools.OkHttp3NoVerifierSSLUtil;
import com.javaee.weixin.xiaochengxu.tools.WeixinUtils;

import net.sf.json.JSONObject;
import okhttp3.RequestBody;
import okhttp3.Response;
/**
 * 小程序支付授权 小程序规定需要谁用https协议,具体配置可自行百度
 * @author Lenovo
 *
 */
@Controller
@RequestMapping("/pay")
public class PaymentController {
	public static final Logger log = LoggerFactory.getLogger(PaymentController.class);
	
	public static final String LOGIN_JSCODE2SESSION = "https://api.weixin.qq.com/sns/jscode2session?appid={APPID}&secret={SECRET}&js_code={JSCODE}&grant_type=authorization_code";
	public static final String UNIFIEDORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";

	public static final String WX_APPID = "xxx"; //小程序appid
	public static final String WX_SECRET = "xxxxx"; //小程序秘钥;
	/* 商户号 */
	public static final String WX_MCH_ID = "xxxxx"; //商户号
	public static final String WX_API_KEY = "xxxxxxx";//32位API秘钥，可到商户平台-API安全里设置
	public static final String WX_NOTIFY_URL = "https://xxxxx.com/pay/notifyurl.shtml";//支付成功后的回调地址

	@Autowired
	ObjectMapper objectMapper;

	@Autowired
	SqlSession sqlSession;

	/**
	 * 小程序支付,参数可根据自己的业务相应的调整
	 * @param request
	 * @param unifiedorderDto
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value = "unifiedorder", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public PaymentDto unifiedorder(HttpServletRequest request,@org.springframework.web.bind.annotation.RequestBody UnifiedorderDto unifiedorderDto) throws  Exception {
		XmlMapper xmlMapper = new XmlMapper();
		if(StringUtils.isBlank(unifiedorderDto.getOpenid()) || StringUtils.isBlank(unifiedorderDto.getProductId())){
			throw new CommonException("openid is null");
		}
		String companyId = request.getParameter("companyId");
		String userName = request.getParameter("userName");
		if(StringUtils.isBlank(companyId)){
			throw new CommonException("企业号不能为空!");
		}
		if(StringUtils.isBlank(userName)){
			throw new CommonException("用户账号不能为空!");
		}
		unifiedorderDto.setTotalFee(Double.parseDouble(unifiedorderDto.getTotalFee())/100);
		unifiedorderDto.setBody("余额充值");
		unifiedorderDto.setOutTradeNo(unifiedorderDto.getProductId());
		unifiedorderDto.setDetail("支付详情");
		unifiedorderDto.setSpbillCreateIp(IPUtil.getIp(request));
		unifiedorderDto.setOpenid(unifiedorderDto.getOpenid());//openid
		unifiedorderDto.setAppid(WX_APPID);
		unifiedorderDto.setMchId(WX_MCH_ID);
		String str = "";
		str=userName+","+companyId;
		unifiedorderDto.setAttach(str);//此处为企业号和用户账号
		unifiedorderDto.setNonceStr(UUID.randomUUID().toString().replace("-", ""));
		unifiedorderDto.setSignType("MD5");
		unifiedorderDto.setFeeType("CNY");
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
		unifiedorderDto.setTimeStart(sdf.format(new Date()));
		unifiedorderDto.setTimeExpire(sdf.format(new Date(System.currentTimeMillis() + 1000 * 60 * 30)));
		// 商品标记，使用代金券或立减优惠功能时需要的参数，说明详见代金券或立减优惠
		// unifiedorderDto.setGoodsTag("");
		unifiedorderDto.setNotifyUrl(String.format(PaymentController.WX_NOTIFY_URL,userName));
		unifiedorderDto.setTradeType("JSAPI");
		// 上传此参数no_credit--可限制用户不能使用信用卡支付
		unifiedorderDto.setLimitPay("no_credit");
		unifiedorderDto.setSign(WX_API_KEY);

		try {
			Response response = OkHttp3NoVerifierSSLUtil.getInstance().post(OkHttp3NoVerifierSSLUtil.HEADERS_XML, PaymentController.UNIFIEDORDER_URL,
					RequestBody.create(OkHttp3NoVerifierSSLUtil.MediaType_XML, xmlMapper.writeValueAsString(unifiedorderDto)));
			if (!response.isSuccessful()) {
				log.error("login error: %s %s", PaymentController.UNIFIEDORDER_URL, response);
			}

			String body = response.body().string();
			UnifiedorderResultDto unifiedorderResultDto = xmlMapper.readValue(body, UnifiedorderResultDto.class);
			System.out.println("=========我是可爱的body======"+body);
			// 检查回调的数据是否被篡改,resultCode, returnCode
			if (unifiedorderResultDto.checkSign(WX_API_KEY) && UnifiedorderResultDto.TYPE_SUCCESS.equals(unifiedorderResultDto.getResultCode())
					&& UnifiedorderResultDto.TYPE_SUCCESS.equals(unifiedorderResultDto.getReturnCode())) {
				PaymentDto paymentDto = new PaymentDto();
				paymentDto.setAppId(WX_APPID);
				paymentDto.setTimeStamp(Long.toString(System.currentTimeMillis() / 1000));
				paymentDto.setNonceStr(UUID.randomUUID().toString().replace("-", ""));
				paymentDto.setPackagz(String.format("prepay_id=%s", unifiedorderResultDto.getPrepayId()));
				paymentDto.setSignType("MD5");
				paymentDto.setPaySign(WX_API_KEY);
				return paymentDto;
			}else{
				log.error(body);
			}
		} catch (IOException e) {
			throw new CommonException(e);
		}
		
		return new PaymentDto();

	}
	
	/**
	 * 微信支付回调地址，支付结果通知（异步）
	 */
	@RequestMapping(value="/notifyurl",produces="text/xml;charset=UTF-8")
	@ResponseBody
	public String notifyUrl(@org.springframework.web.bind.annotation.RequestBody String notifyXML) throws Exception{
		// 把输入流携带的字节数组数据转换成字符串
		//String notifyXML = IOUtils.toString(body);
		//String notifyXML=FileUtils.readFileToString(new File(PaymentController.class.getResource("1").getPath()), "UTF-8");
		log.info("notifyUrl:=========="+notifyXML);
		String responseXML="";
		
		if(notifyXML!=null && !notifyXML.trim().isEmpty()){
			Map<String, Object> notifyMap = WeixinUtils.getMapFromXML(notifyXML);
			String attach = notifyMap.get("attach")+"";//附加数据
			String arr [] = attach.split(",");
			String userName = arr[0];
			String company_id = arr[1];
			
			double total_fee = Double.parseDouble((String) notifyMap.get("total_fee"));
			// 支付成功
			if("SUCCESS".equals(notifyMap.get("result_code")+"")){
				responseXML="<xml><return_code><![CDATA[SUCCESS]]></return_code>"
						+ "<return_msg><![CDATA[OK]]></return_msg></xml>";
				//业务逻辑....
			}else{// 支付失败
				responseXML=responseXML.replaceAll("SUCCESS", "FAIL");
			}
		}
		System.out.println(responseXML);
		return responseXML;
	}
	
	/**
	 * 获取 openid
	 */
	@ResponseBody
	@RequestMapping(value = "/getOpenId", method = RequestMethod.GET)
	public static JSONObject sendPost(String appid, String secret, String js_code, String grant_type) {
		PrintWriter out = null;
		BufferedReader in = null;
		String result = "";
		try {
			URL realUrl = new URL("https://api.weixin.qq.com/sns/jscode2session");
			// 打开和URL之间的连接
			URLConnection conn = realUrl.openConnection();
			// 设置通用的请求属性
			conn.setRequestProperty("accept", "*/*");
			conn.setRequestProperty("connection", "Keep-Alive");
			conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
			// conn.setRequestProperty("Charset", "UTF-8");
			// 发送POST请求必须设置如下两行
			conn.setDoOutput(true);
			conn.setDoInput(true);
			// 获取URLConnection对象对应的输出流
			out = new PrintWriter(conn.getOutputStream());
			// 设置请求属性
			String param = "appid=" + appid + "&secret=" + secret + "&js_code=" + js_code + "&grant_type=" + grant_type;
			// 发送请求参数
			out.print(param);
			// flush输出流的缓冲
			out.flush();
			// 定义BufferedReader输入流来读取URL的响应
			in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
			String line;
			while ((line = in.readLine()) != null) {
				result += line;
			}

		} catch (Exception e) {
			System.err.println("发送 POST 请求出现异常！" + e);
			e.printStackTrace();
		}
		// 使用finally块来关闭输出流、输入流
		finally {
			if (out != null) {
				out.close();
			}
		}
		JSONObject json = JSONObject.fromObject(result);
		return json;
	}
	
}
